package com.yunfeisoft.controller.business;

import com.alibaba.excel.EasyExcel;
import com.applet.base.BaseController;
import com.applet.utils.*;
import com.yunfeisoft.business.model.*;
import com.yunfeisoft.business.service.inter.*;
import com.yunfeisoft.excel.listener.ProductExcelListener;
import com.yunfeisoft.model.User;
import com.yunfeisoft.utils.ApiUtils;
import com.yunfeisoft.utils.OrderItemNum;
import com.yunfeisoft.utils.PinyinUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.*;

/**
 * ClassName: ProductController
 * Description: 商品信息Controller
 * Author: Jackie liu
 * Date: 2020-07-23
 */
@Controller
public class ProductController extends BaseController {

    @Autowired
    private ProductService productService;
    @Autowired
    private CodeBuilderService codeBuilderService;
    @Autowired
    private ProductCategoryService productCategoryService;
    @Autowired
    private SupplierService supplierService;
    @Autowired
    private WarehouseProductService warehouseProductService;
    @Autowired
    private SaleItemService saleItemService;
    @Autowired
    private PurchaseItemService purchaseItemService;
    @Autowired
    private AllotItemService allotItemService;
    @Autowired
    private IndecItemService indecItemService;

    /**
     * 添加商品信息
     *
     * @param record
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/web/product/save", method = RequestMethod.POST)
    @ResponseBody
    public Response save(Product record, HttpServletRequest request, HttpServletResponse response) {
        Validator validator = new Validator();
        validator.required(request, "name", "名称为空");
        //validator.required(request, "categoryId", "类别为空");
        //validator.required(request, "supplierId", "供应商为空");
        //validator.required(request, "buyPrice", "进货价为空");
        validator.number(request, "buyPrice", "进货价不合法");
        validator.number(request, "salePrice", "零售价不合法");
        validator.number(request, "memberPrice", "会员价不合法");
        validator.number(request, "tradePrice", "批发价不合法");
        validator.required(request, "warehouseProductsStr", "库存信息为空");
        if (validator.isError()) {
            return ResponseUtils.warn(validator.getMessage());
        }

        User user = ApiUtils.getLoginUser();
        boolean dupName = productService.isDupName(user.getOrgId(), record.getId(), record.getName());
        if (dupName) {
            return ResponseUtils.warn("该名称已经存在");
        }

        record.setId(KeyUtils.getKey());
        String warehouseProductsStr = ServletRequestUtils.getStringParameter(request, "warehouseProductsStr", null);
        List<WarehouseProduct> warehouseProductList = FastJsonUtils.jsonToList(warehouseProductsStr, WarehouseProduct.class);
        record.setWarehouseProductList(warehouseProductList);
        for (WarehouseProduct item : warehouseProductList) {
            item.setProductId(record.getId());
            item.setStock(item.getStock() == null ? BigDecimal.ZERO : item.getStock());
            item.setInitStock(item.getStock());
            item.setShortageLimit(item.getShortageLimit() == null ? BigDecimal.ZERO : item.getShortageLimit());
            item.setBacklogLimit(item.getBacklogLimit() == null ? BigDecimal.ZERO : item.getBacklogLimit());
        }

        record.setBuyPrice(record.getBuyPrice() == null ? BigDecimal.ZERO : record.getBuyPrice());
        record.setSalePrice(record.getSalePrice() == null ? BigDecimal.ZERO : record.getSalePrice());
        record.setMemberPrice(record.getMemberPrice() == null ? BigDecimal.ZERO : record.getMemberPrice());
        record.setTradePrice(record.getTradePrice() == null ? BigDecimal.ZERO : record.getTradePrice());
        record.setAvgPrice(record.getBuyPrice());

        record.setOrgId(user.getOrgId());

        if (StringUtils.isBlank(record.getCode())) {
            String code = codeBuilderService.generateCode("PRODUCT", 4, user.getOrgId());
            record.setCode(code);
        } else {
            boolean dupCode = productService.isDupCode(user.getOrgId(), record.getId(), record.getCode());
            if (dupCode) {
                return ResponseUtils.warn("该编码已经存在");
            }
        }

        if (StringUtils.isBlank(record.getPinyinCode())) {
            record.setPinyinCode(PinyinUtils.getPinYinHeadChar(record.getName()));
        } else {
            record.setPinyinCode(record.getPinyinCode().toUpperCase());
        }
        productService.save(record);
        return ResponseUtils.success("保存成功");
    }

    /**
     * 修改商品信息
     *
     * @param record
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/web/product/modify", method = RequestMethod.POST)
    @ResponseBody
    public Response modify(Product record, HttpServletRequest request, HttpServletResponse response) {
        Validator validator = new Validator();
        validator.required(request, "id", "参数错误");
        validator.required(request, "name", "名称为空");
        //validator.required(request, "categoryId", "类别为空");
        //validator.required(request, "supplierId", "供应商为空");
        //validator.required(request, "buyPrice", "进货价为空");
        validator.number(request, "buyPrice", "进货价不合法");
        validator.number(request, "salePrice", "零售价不合法");
        validator.number(request, "memberPrice", "会员价不合法");
        validator.number(request, "tradePrice", "批发价不合法");
        validator.required(request, "warehouseProductsStr", "库存信息为空");
        if (validator.isError()) {
            return ResponseUtils.warn(validator.getMessage());
        }

        User user = ApiUtils.getLoginUser();
        boolean dupName = productService.isDupName(user.getOrgId(), record.getId(), record.getName());
        if (dupName) {
            return ResponseUtils.warn("该名称已经存在");
        }

        if (StringUtils.isNotBlank(record.getCode())) {
            boolean dupCode = productService.isDupCode(user.getOrgId(), record.getId(), record.getCode());
            if (dupCode) {
                return ResponseUtils.warn("该编码已经存在");
            }
        }

        String warehouseProductsStr = ServletRequestUtils.getStringParameter(request, "warehouseProductsStr", null);
        List<WarehouseProduct> warehouseProductList = FastJsonUtils.jsonToList(warehouseProductsStr, WarehouseProduct.class);
        record.setWarehouseProductList(warehouseProductList);
        for (WarehouseProduct item : warehouseProductList) {
            item.setProductId(record.getId());
            item.setStock(null);
            item.setInitStock(item.getInitStock() == null ? BigDecimal.ZERO : item.getInitStock());
            item.setShortageLimit(item.getShortageLimit() == null ? BigDecimal.ZERO : item.getShortageLimit());
            item.setBacklogLimit(item.getBacklogLimit() == null ? BigDecimal.ZERO : item.getBacklogLimit());
        }

        record.setBuyPrice(record.getBuyPrice() == null ? BigDecimal.ZERO : record.getBuyPrice());
        record.setSalePrice(record.getSalePrice() == null ? BigDecimal.ZERO : record.getSalePrice());
        record.setMemberPrice(record.getMemberPrice() == null ? BigDecimal.ZERO : record.getMemberPrice());
        record.setTradePrice(record.getTradePrice() == null ? BigDecimal.ZERO : record.getTradePrice());
        //record.setStock(record.getStock() == null ? BigDecimal.ZERO : record.getStock());
        //record.setShortageLimit(record.getShortageLimit() == null ? BigDecimal.ZERO : record.getShortageLimit());
        //record.setBacklogLimit(record.getBacklogLimit() == null ? BigDecimal.ZERO : record.getBacklogLimit());

        if (StringUtils.isBlank(record.getPinyinCode())) {
            record.setPinyinCode(PinyinUtils.getPinYinHeadChar(record.getName()));
        } else {
            record.setPinyinCode(record.getPinyinCode().toUpperCase());
        }

        productService.modify(record);
        return ResponseUtils.success("保存成功");
    }

    /**
     * 修改商品条码
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/web/product/modifyCode", method = RequestMethod.POST)
    @ResponseBody
    public Response modifyCode(HttpServletRequest request, HttpServletResponse response) {
        Validator validator = new Validator();
        validator.required(request, "id", "参数错误");
        validator.required(request, "code", "条码为空");
        if (validator.isError()) {
            return ResponseUtils.warn(validator.getMessage());
        }

        String id = ServletRequestUtils.getStringParameter(request, "id", null);
        String code = ServletRequestUtils.getStringParameter(request, "code", null);

        User user = ApiUtils.getLoginUser();
        boolean dupCode = productService.isDupCode(user.getOrgId(), id, code);
        if (dupCode) {
            return ResponseUtils.warn("该编码已经存在");
        }

        Product record = new Product();
        record.setId(id);
        record.setCode(code);

        productService.modify(record);
        return ResponseUtils.success("保存成功");
    }

    /**
     * 查询商品信息
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/web/product/query", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public Response query(HttpServletRequest request, HttpServletResponse response) {
        String id = ServletRequestUtils.getStringParameter(request, "id", null);
        if (StringUtils.isBlank(id)) {
            return ResponseUtils.warn("参数错误");
        }
        Product record = productService.load(id);

        if (record != null) {
            ProductCategory productCategory = productCategoryService.load(record.getCategoryId());
            if (productCategory != null) {
                record.setCategoryName(productCategory.getName());
            }

            Supplier supplier = supplierService.load(record.getSupplierId());
            if (supplier != null) {
                record.setSupplierName(supplier.getName());
            }

            Map<String, Object> params = new HashMap<>();
            params.put("productId", id);
            List<WarehouseProduct> warehouseProductList = warehouseProductService.queryList(params);
            record.setWarehouseProductList(warehouseProductList);
        }
        return ResponseUtils.success(record);
    }

    /**
     * 分页查询商品信息
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/web/product/list", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public Response list(HttpServletRequest request, HttpServletResponse response) {
        String name = ServletRequestUtils.getStringParameter(request, "name", null);
        String namePinyin = ServletRequestUtils.getStringParameter(request, "namePinyin", null);

        User user = ApiUtils.getLoginUser();

        Map<String, Object> params = new HashMap<String, Object>();
        initParams(params, request);
        params.put("name", name);
        params.put("namePinyin", namePinyin);
        params.put("orgId", user.getOrgId());

        Page<Product> page = productService.queryPage(params);
        return ResponseUtils.success(page);
    }

    /**
     * 批量删除商品信息
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/web/product/delete", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public Response delete(HttpServletRequest request, HttpServletResponse response) {
        String ids = ServletRequestUtils.getStringParameter(request, "ids", null);
        if (StringUtils.isBlank(ids)) {
            return ResponseUtils.warn("参数错误");
        }
        productService.remove(ids.split(","));
        return ResponseUtils.success("删除成功");
    }

    /**
     * 导出excel
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/web/product/exportExcel", method = {RequestMethod.POST, RequestMethod.GET})
    public void exportExcel(HttpServletRequest request, HttpServletResponse response) {
        String name = ServletRequestUtils.getStringParameter(request, "name", null);

        /*if (StringUtils.isNotBlank(name)) {
            try {
                name = new String(name.getBytes("ISO8859-1"), "UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }*/
        User user = ApiUtils.getLoginUser();

        Map<String, Object> params = new HashMap<String, Object>();
        params.put("name", name);
        params.put("orgId", user.getOrgId());

        List<Product> list = productService.queryList(params);
        try {
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            String fileName = URLEncoder.encode("商品信息_" + DateUtils.getNowTime(), "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");

            // 根据用户传入字段 假设我们要忽略 date
            Set<String> excludeColumnFiledNames = new HashSet<String>();
            excludeColumnFiledNames.add("id");
            excludeColumnFiledNames.add("orgId");
            excludeColumnFiledNames.add("categoryId");
            excludeColumnFiledNames.add("supplierId");
            excludeColumnFiledNames.add("isDel");
            excludeColumnFiledNames.add("exists");
            excludeColumnFiledNames.add("createTime");
            excludeColumnFiledNames.add("modifyTime");
            excludeColumnFiledNames.add("createId");
            excludeColumnFiledNames.add("modifyId");

            // 这里需要设置不关闭流
            EasyExcel.write(response.getOutputStream(), Product.class)
                    .excludeColumnFiledNames(excludeColumnFiledNames)
                    .autoCloseStream(Boolean.FALSE)
                    .sheet("商品信息")
                    .doWrite(list);

        } catch (Exception e) {
            e.printStackTrace();
            // 重置response
            response.reset();
            //response.setContentType("application/json");
            //response.setCharacterEncoding("utf-8");
            AjaxUtils.ajaxJsonWarnMessage("下载失败");
        }
    }

    /**
     * 导入excel
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/web/product/importExcel", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public Response importExcel(@RequestParam("file") MultipartFile file, HttpServletRequest request, HttpServletResponse response) {
        try {
            User user = ApiUtils.getLoginUser();
            EasyExcel.read(file.getInputStream(), Product.class, new ProductExcelListener(user.getOrgId(), user.getId())).sheet().doRead();
        } catch (IOException e) {
            e.printStackTrace();
            return ResponseUtils.success("解析导入文件异常");
        }
        return ResponseUtils.success("导入成功");
    }

    /**
     * 库存变化
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/web/product/stockChange", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public Response stockChange(HttpServletRequest request, HttpServletResponse response) {
        String productId = ServletRequestUtils.getStringParameter(request, "productId", null);
        if (StringUtils.isBlank(productId)) {
            return ResponseUtils.warn("商品参数错误");
        }

        WarehouseProduct warehouseProduct = warehouseProductService.queryStockSum(productId);

        User user = ApiUtils.getLoginUser();

        Map<String, OrderItemNum> numMap = new HashMap<>();
        List<OrderItemNum> numList = new ArrayList<>();

        List<OrderItemStatistics> statisticsList = saleItemService.queryStatistics(user.getOrgId(), productId);
        for (OrderItemStatistics orderItemStatistics : statisticsList) {
            OrderItemNum item = numMap.get(orderItemStatistics.getDay());
            if (item == null) {
                item = new OrderItemNum();
                item.setDate(orderItemStatistics.getDay());
                //item.setStock(warehouseProduct.getStock());
                item.setInitStock(warehouseProduct.getInitStock());
                numMap.put(orderItemStatistics.getDay(), item);
                numList.add(item);
            }

            BigDecimal num = item.getSaleNum() == null ? BigDecimal.ZERO : item.getSaleNum();
            item.setSaleNum(num.add(orderItemStatistics.getTotalQuantity()));
        }

        statisticsList = purchaseItemService.queryStatistics(user.getOrgId(), productId);
        for (OrderItemStatistics orderItemStatistics : statisticsList) {
            OrderItemNum item = numMap.get(orderItemStatistics.getDay());
            if (item == null) {
                item = new OrderItemNum();
                item.setDate(orderItemStatistics.getDay());
                //item.setStock(warehouseProduct.getStock());
                item.setInitStock(warehouseProduct.getInitStock());
                numMap.put(orderItemStatistics.getDay(), item);
                numList.add(item);
            }

            BigDecimal num = item.getPurchaseNum() == null ? BigDecimal.ZERO : item.getPurchaseNum();
            item.setPurchaseNum(num.add(orderItemStatistics.getTotalQuantity()));
        }

        statisticsList = allotItemService.queryStatistics(user.getOrgId(), productId);
        for (OrderItemStatistics orderItemStatistics : statisticsList) {
            OrderItemNum item = numMap.get(orderItemStatistics.getDay());
            if (item == null) {
                item = new OrderItemNum();
                item.setDate(orderItemStatistics.getDay());
                //item.setStock(warehouseProduct.getStock());
                item.setInitStock(warehouseProduct.getInitStock());
                numMap.put(orderItemStatistics.getDay(), item);
                numList.add(item);
            }

            BigDecimal num = item.getAllotNum() == null ? BigDecimal.ZERO : item.getAllotNum();
            item.setAllotNum(num.add(orderItemStatistics.getTotalQuantity()));
        }

        statisticsList = indecItemService.queryStatistics(user.getOrgId(), productId);
        for (OrderItemStatistics orderItemStatistics : statisticsList) {
            OrderItemNum item = numMap.get(orderItemStatistics.getDay());
            if (item == null) {
                item = new OrderItemNum();
                item.setDate(orderItemStatistics.getDay());
                //item.setStock(warehouseProduct.getStock());
                item.setInitStock(warehouseProduct.getInitStock());
                numMap.put(orderItemStatistics.getDay(), item);
                numList.add(item);
            }

            BigDecimal num = item.getIndecNum() == null ? BigDecimal.ZERO : item.getIndecNum();
            item.setIndecNum(num.add(orderItemStatistics.getTotalQuantity()));
        }

        Collections.sort(numList, new Comparator<OrderItemNum>() {
            @Override
            public int compare(OrderItemNum o1, OrderItemNum o2) {
                return o1.getDate().compareTo(o2.getDate());
            }
        });

        BigDecimal initStock = warehouseProduct.getInitStock() == null ? BigDecimal.ZERO : warehouseProduct.getInitStock();
        BigDecimal totalPurchaseNum = BigDecimal.ZERO;
        BigDecimal totalSaleNum = BigDecimal.ZERO;
        BigDecimal totalAllotNum = BigDecimal.ZERO;
        BigDecimal totalIndecNum = BigDecimal.ZERO;

        for (int i = 0, size = numList.size(); i < size; i++) {
            OrderItemNum itemNum = numList.get(i);
            itemNum.setInitStock(initStock);
            initStock = itemNum.getCaclStock();

            totalPurchaseNum = totalPurchaseNum.add(itemNum.getPurchaseNum() == null ? BigDecimal.ZERO : itemNum.getPurchaseNum());
            totalSaleNum = totalSaleNum.add(itemNum.getSaleNum() == null ? BigDecimal.ZERO : itemNum.getSaleNum());
            totalAllotNum = totalAllotNum.add(itemNum.getAllotNum() == null ? BigDecimal.ZERO : itemNum.getAllotNum());
            totalIndecNum = totalIndecNum.add(itemNum.getIndecNum() == null ? BigDecimal.ZERO : itemNum.getIndecNum());
        }

        OrderItemNum item = new OrderItemNum();
        item.setDate("合计");
        item.setStock(warehouseProduct.getStock());
        item.setInitStock(warehouseProduct.getInitStock());
        item.setPurchaseNum(totalPurchaseNum);
        item.setSaleNum(totalSaleNum);
        item.setAllotNum(totalAllotNum);
        item.setIndecNum(totalIndecNum);
        numList.add(item);
        return ResponseUtils.success(numList);
    }
}
